package com.lslk.othello.ai;

import com.lslk.othello.models.Game;
import com.lslk.othello.models.Position;
import com.lslk.othello.models.Position.Occupation;

public class GameBoard {
	public static String[] mNames=new String[]{"A1","B1","C1","D1","E1","F1","G1","H1",
												"A2","B2","C2","D2","E2","F2","G2","H2",
												"A3","B3","C3","D3","E3","F3","G3","H3",
												"A4","B4","C4","D4","E4","F4","G4","H4",
												"A5","B5","C5","D5","E5","F5","G5","H5",
												"A6","B6","C6","D6","E6","F6","G6","H6",
												"A7","B7","C7","D7","E7","F7","G7","H7",
												"A8","B8","C8","D8","E8","F8","G8","H8"};
/*
 *  0  1  2  3  4  5  6  7
 *  8  9 10 11 12 13 14 15
 * 16 17 18 19 20 21 22 23
 * 24 25 26 27 28 29 30 31
 * 32 33 34 35 36 37 38 39
 * 40 41 42 43 44 45 46 47
 * 48 49 50 51 52 53 54 55
 * 56 57 58 59 60 61 62 63
 */
/**
 * This function is almost the same as the one in GameFunctions.
 * The other one should get deprecated and get this one move there. 
 * Not sure if I will have the motivation to do so for this project. 
 */
public static boolean isLegal(final int[] pieces,final int pos,final int same){
	if(pieces[pos]!=0) 
		return false;
	boolean r=false;
	int i,end,counter,occ,empty=0;
	//Check Horizontal Left;
	counter=0;
	end=pos-pos%8;
	for(i=pos-1;i>=end;i--){
		occ=pieces[i];
		if(occ==empty)
			break;
		if(occ==same){
			if(counter==0)
				break;
			else{
				r=true;
			}
		}else
			counter++;
	}
	if(r)
		return r;
	//Check Horizontal Right;
	counter=0;
	end=pos+(8-pos%8);
	for(i=pos+1;i<end;i++){
		occ=pieces[i];
		if(occ==empty)
			break;
		if(occ==same){
			if(counter==0)
				break;
			else{
				r=true;
			}
		}else
			counter++;
	}
	if(r)
		return r;
	//Check Vertical Up;
	counter=0;
	end=pos%8;
	for(i=pos-8;i>=end;i-=8){
		occ=pieces[i];
		if(occ==empty)
			break;
		if(occ==same){
			if(counter==0)
				break;
			else{
				r=true;
			}
		}else
			counter++;
	}
	if(r)
		return r;
	//Check Vertical Down;
	counter=0;
	end=56+pos%8;
	for(i=pos+8;i<=end;i+=8){
		occ=pieces[i];
		if(occ==empty)
			break;
		if(occ==same){
			if(counter==0)
				break;
			else{
				r=true;
			}
		}else
			counter++;
	}
	if(r)
		return r;
	//Check Upper Left;
	counter=0;
	if(pos%8!=0)
	for(i=pos-9;(i>=0);i-=9){
		occ=pieces[i];
		if(occ==empty)
			break;
		if(occ==same){
			if(counter==0)
				break;
			else{
				r=true;
			}
		}else
			counter++;
		if(i%8==0)
			break;
	}
	if(r)
		return r;
	//Check Upper Right;
	counter=0;
	if(pos%8!=7)
	for(i=pos-7;(i>0);i-=7){
		occ=pieces[i];
		if(occ==empty)
			break;
		if(occ==same){
			if(counter==0)
				break;
			else{
				r=true;
			}
		}else
			counter++;
		if(i%8==7)
			break;
	}
	if(r)
		return r;
	//Check Down Left;
	counter=0;
	if(pos%8!=0)
	for(i=pos+7;(i<63);i+=7){
		occ=pieces[i];
		if(occ==empty)
			break;
		if(occ==same){
			if(counter==0)
				break;
			else{
				r=true;
			}
		}else
			counter++;
		if(i%8==0)
			break;
	}
	if(r)
		return r;
	//Check Down Right;
	counter=0;
	if(pos%8!=7)
	for(i=pos+9;(i<=63);i+=9){
		occ=pieces[i];
		if(occ==empty)
			break;	
		if(occ==same){
			if(counter==0)
				break;
			else{
				r=true;
			}
		}else
			counter++;
		if(i%8==7)
			break;
	}
	return r;
}
public static int isOver(final int[] positions,int skiped){
	int black=0,white=0;
	for(int p:positions){
		switch(p){
			case 1: white++; break;
			case 2: black++; break;
		}
	}
	if(black<=0)
		return 2;
	if(white<=0)
		return 3;
	if( (black+white)>=64 || skiped>=2){
		if(black>white)
			return 3;
		if(black==white)
			return 1;
		return 2;
	}
	return 0;
}
public interface Result{
	public static final int NOT_OVER=0;
	public static final int TIE=1;
	public static final int WHITE_WIN=2;
	public static final int BLACK_WIN=3;
}
final static int[] turns=new int[8];
public static int[] resultFrom(final int[] original, final int pos, final int same) {
	//Log.i(TAG,"Process last move: "+pos);
	final int opp=(same==1)?2:1;
	final int[] pieces=original.clone();
	pieces[pos]=same;
	int i,end,counter,occ;
	final int empty=0;
	boolean canTurn;
	//Horizontal Left
	canTurn=false;
	counter=0;
	end=pos-pos%8;
	for(i=pos-1;i>=end;i--){
		//Log.i(TAG,"Horizontal Left "+i);
		occ=pieces[i];
		if(occ==empty)
			break;
		if(occ==same){
			canTurn=true;
			break;
		}else{
			turns[counter]=i;
			counter++;
		}
	}	
	if(canTurn)
		for(i=0;i<counter;i++)
			pieces[turns[i]]=opp;
	//Check Horizontal Right;
	canTurn=false;
	counter=0;
	end=pos+(8-pos%8);
	for(i=pos+1;i<end;i++){
		//Log.i(TAG,"Horizontal Right "+i);
		occ=pieces[i];
		if(occ==empty)
			break;
		if(occ==same){
			canTurn=true;
			break;
		}else{
			//Log.i(TAG,"Recorded: "+i+" counter:"+ (counter+1));
			turns[counter]=i;
			counter++;
		}
	}	
	
	if(canTurn)
		for(i=0;i<counter;i++)
			pieces[turns[i]]=opp;
	//Check Vertical Up;
	canTurn=false;
	counter=0;
	end=pos%8;
	for(i=pos-8;i>=end;i-=8){
		occ=pieces[i];
		if(occ==empty)
			break;
		if(occ==same){
			canTurn=true;
			break;
		}else{
			turns[counter]=i;
			counter++;
		}
	}	
	if(canTurn)
		for(i=0;i<counter;i++)
			pieces[turns[i]]=opp;
	//Check Vertical Down;
	canTurn=false;
	counter=0;
	end=56+pos%8;
	for(i=pos+8;i<=end;i+=8){
		//Log.i(TAG,"Vertical Down "+i);
		occ=pieces[i];
		if(occ==empty)
			break;
		if(occ==same){
			canTurn=true;
			break;
		}else{
			turns[counter]=i;
			counter++;
		}
	}	
	if(canTurn)
		for(i=0;i<counter;i++)
			pieces[turns[i]]=opp;
	//Check Upper Left;
	canTurn=false;
	counter=0;
	if(pos%8!=0)
	for(i=pos-9;(i>=0);i-=9){
		//Log.i(TAG,"Upper Left "+i);
		occ=pieces[i];
		if(occ==empty)
			break;
		if(occ==same){
			canTurn=true;
			break;
		}else{
			turns[counter]=i;
			counter++;
		}
		if(i%8==0)
			break;
	}	
	if(canTurn)
		for(i=0;i<counter;i++)
			pieces[turns[i]]=opp;
	//Check Upper Right;
	canTurn=false;
	counter=0;
	if(pos%8!=7)
	for(i=pos-7;(i>0);i-=7){
		occ=pieces[i];
		if(occ==empty)
			break;
		if(occ==same){
			canTurn=true;
			break;
		}else{
			turns[counter]=i;
			counter++;
		}
		 if(i%8==7)
			 break;
	}	
	if(canTurn)
		for(i=0;i<counter;i++)
			pieces[turns[i]]=opp;
	//Check Down Left;
	canTurn=false;
	counter=0;
	if(pos%8!=0)
	for(i=pos+7;(i<63);i+=7){
		occ=pieces[i];
		if(occ==empty)
			break;
		if(occ==same){
			canTurn=true;
			break;
		}else{
			turns[counter]=i;
			counter++;
		}
		if(i%8==0)
			break;
	}	
	if(canTurn)
		for(i=0;i<counter;i++)
			pieces[turns[i]]=opp;
	//Check Down Right;
	canTurn=false;
	counter=0;
	if(pos%8!=7)
	for(i=pos+9;(i<=63);i+=9){
		//Log.i(TAG,"Down Right "+i);
		occ=pieces[i];
		if(occ==empty)
			break;
		if(occ==same){
			canTurn=true;
			break;
		}else{
			turns[counter]=i;
			counter++;
		}
		 if(i%8==7)
			 break;
	}	
	if(canTurn)
		for(i=0;i<counter;i++)
			pieces[turns[i]]=opp;
	return pieces;
}
/**
 * Check if game is over and announce the winner.
 * @param g
 */
public static int isOver(final Game g){
	int black=0,white=0;
	final int isWhite=Occupation.WHITE,isBlack=Occupation.BLACK;
	for(Position p:g.positions){
		switch(p.occupation){
			case isWhite: white++; break;
			case isBlack: black++; break;
		}
	}
	if(black==0)
		return Result.WHITE_WIN;
	if(white==0)
		return Result.BLACK_WIN;
	if( (black+white)>=64 || g.skiped==1){
		if(black>white)
			return Result.BLACK_WIN;
		if(black==white)
			return Result.TIE;
		return Result.WHITE_WIN;
	}
	return Result.NOT_OVER;
}
public static int numTurned(int[] pieces, int pos, int same) {
	pieces[pos]=same;
	int i,end,counter=0,occ,empty=0;
	//Horizontal Left
	end=pos-pos%8;
	for(i=pos-1;i>=end;i--){
		occ=pieces[i];
		if(occ==empty)
			break;
		if(occ==same){
			break;
		}else{
			counter++;
		}
	}	
	//Check Horizontal Right;
	end=pos+(8-pos%8);
	for(i=pos+1;i<end;i++){
		occ=pieces[i];
		if(occ==empty)
			break;
		if(occ==same){
			break;
		}else{
			counter++;
		}
	}	
	//Check Vertical Up;
	end=pos%8;
	for(i=pos-8;i>=end;i-=8){
		occ=pieces[i];
		if(occ==empty)
			break;
		if(occ==same){
			break;
		}else{
			counter++;
		}
	}	
	//Check Vertical Down;
	end=56+pos%8;
	for(i=pos+8;i<=end;i+=8){
		occ=pieces[i];
		if(occ==empty)
			break;
		if(occ==same){
			break;
		}else{
			counter++;
		}
	}	
	//Check Upper Left;
	if(pos%8!=0)
	for(i=pos-9;(i>=0);i-=9){
		occ=pieces[i];
		if(occ==empty)
			break;
		if(occ==same){
			break;
		}else{
			counter++;
		}
		if(i%8==0)
			break;
	}	
	//Check Upper Right;
	if(pos%8!=7)
	for(i=pos-7;(i>0);i-=7){
		occ=pieces[i];
		if(occ==empty)
			break;
		if(occ==same){
			break;
		}else{
			counter++;
		}
		 if(i%8==7)
			 break;
	}	
	//Check Down Left;
	if(pos%8!=0)
	for(i=pos+7;(i<63);i+=7){
		occ=pieces[i];
		if(occ==empty)
			break;
		if(occ==same){
			break;
		}else{
			counter++;
		}
		if(i%8==0)
			break;
	}	
	//Check Down Right;
	if(pos%8!=7)
	for(i=pos+9;(i<=63);i+=9){
		occ=pieces[i];
		if(occ==empty)
			break;
		if(occ==same){
			break;
		}else{
			counter++;
		}
		 if(i%8==7)
			 break;
	}	
	return counter;
}
}